﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BbsbWebService.Classes;
using System.IO;
using System.Xml.Linq;
using BbsbWebService.Enums;
using BbsbWebService.Service;
using BbsbWebService.Service.Update;
using BbsbWebService.Repositories.Server;

namespace BbsbWebService.Repositories
{
    public class ServerItemRepository : ServerPowerRepositoryBase<ControllableItem>
    {
        public override void Initialise()
        {
            if (File.Exists(AppSettings.SettingsFile.FullName))
            {
                XDocument doc = XDocument.Load(AppSettings.SettingsFile.FullName);

                var items = doc.Descendants("Items");
                foreach (var bob in items.Elements("Item"))
                {
                    ControllableItem item = GetControllableItemFromXElement(bob);
                    Items.Add(item);
                }
            }
            ServerCommon.Initialise();
        }

        protected override PowerState SendPowerBase(CommandItem item, PowerOption option)
        {
            ControllableItem conItem = item as ControllableItem;
            conItem.SendPower(option);
            ServerCommon.UpdateState(item.Id, item.State);
            return item.State;
        }

        public override PowerState Toggle(Guid id)
        {
            PowerState retState = PowerState.Unknown;

            if (HasItem(id))
            {
                var item = GetItem(id);
                PowerState currState = item.State;
                if (currState == PowerState.On)
                {
                    SendPowerBase(item, PowerOption.Off);
                }
                else
                {
                    SendPowerBase(item, PowerOption.On);
                }
                retState = item.State;
            }

            return retState;
        }

        public override void UpdateState(Guid id, PowerState state)
        {
            base.UpdateState(id, state);
            ServerCommon.UpdateState(id, state);
        }

        public override XElement SaveRepository()
        {
            XElement items = new XElement("Items",
               from bob in Items
               select new XElement("Item",
                   new XElement("Id", bob.Id),
                   new XElement("Name", bob.Name),
                   new XElement("ItemType", bob.TypeName),
                   new XElement("Command", bob.Command),
                   new XElement("IsImportant", bob.IsImportant),
                   new XElement("IsAlwaysStateAware", bob.IsAlwaysStateAware),
                   bob.SaveAdditionalProperties(),
                   new XElement("Groups",
                   from itemGroup in bob.Groups
                   select new XElement("Group",
                       new XElement("Id", itemGroup.Id))
                   )
                   )
                           );
            return items;
        }

        private ControllableItem GetControllableItemFromXElement(XElement element)
        {
            string type = element.GetChildValueFromElement<string>("ItemType");
            ControllableItem item = ControllableItemFactory.CreateItem(type);
            item.Id = element.GetChildValueFromElement<Guid>("Id");
            item.Name = element.GetChildValueFromElement<string>("Name");
            item.Command = element.GetChildValueFromElement<string>("Command");
            item.IsImportant = element.GetChildValueFromElement<bool>("IsImportant");
            item.IsAlwaysStateAware = element.GetChildValueFromElement<bool>("IsAlwaysStateAware");
            foreach (var xmlGroup in element.Descendants("Group"))
            {
                Guid id = new Guid(xmlGroup.Value);
                if (RepositoryInstances.GroupRepository.HasItem(id))
                {
                    Group group = RepositoryInstances.GroupRepository.GetItem(id);
                    item.Groups.Add(group);
                }
            }

            item.AddItemDependantProperty(element);

            return item;
        }
    }
}
